/*
 * Copyright (C) 2012 Santiago Valdarrama
 * 
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at 
 * 
 * http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 * 
 */
package com.yuanmei.stockeyes.fragments;

import static com.yuanmei.stockeyes.artifacts.Extensions.isHoneycombOrLater;
import static com.yuanmei.stockeyes.artifacts.Extensions.isIceCreamSandwichOrLater;
import static com.yuanmei.stockeyes.artifacts.Extensions.isPriorIceCreamSandwich;

import java.util.ArrayList;
import java.util.List;

import android.annotation.TargetApi;
import android.app.Activity;
import android.app.AlertDialog;
import android.app.SearchManager;
import android.content.ClipData;
import android.content.Context;
import android.content.DialogInterface;
import android.content.DialogInterface.OnDismissListener;
import android.content.Intent;
import android.content.res.Resources;
import android.content.SharedPreferences;
import android.content.SharedPreferences.Editor;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentActivity;
import android.util.Log;
import android.util.SparseArray;
import android.view.ActionMode;
import android.view.DragEvent;
import android.view.GestureDetector;
import android.view.GestureDetector.SimpleOnGestureListener;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.MotionEvent;
import android.view.View;
import android.view.View.DragShadowBuilder;
import android.view.View.OnClickListener;
import android.view.View.OnLongClickListener;
import android.view.ViewGroup;
import android.view.animation.Animation;
import android.view.animation.Animation.AnimationListener;
import android.view.animation.AnimationUtils;
import android.widget.FrameLayout;
import android.widget.RelativeLayout;
import android.widget.SearchView;
import android.widget.TableLayout;
import android.widget.TableRow.LayoutParams;
import android.widget.TextView;
import android.widget.ViewFlipper;
import android.widget.Toast;

import com.baidu.mobads.AdSettings;
import com.baidu.mobads.AdView;
import com.baidu.mobads.AdViewListener;
import com.baidu.mobads.AppActivity;

import com.yuanmei.stockeyes.R;
import com.yuanmei.stockeyes.activities.PrefersActivity;
import com.yuanmei.stockeyes.activities.StockAnalysisActivity;
import com.yuanmei.stockeyes.artifacts.Constants;
import com.yuanmei.stockeyes.artifacts.Extensions;
import com.yuanmei.stockeyes.artifacts.Extensions.PatternBackgroundColor;
import com.yuanmei.stockeyes.artifacts.StockTileProcessor;
import com.yuanmei.stockeyes.artifacts.StockTileProcessor.OnDragTileListener;
import com.yuanmei.stockeyes.artifacts.StockTileViewHolder;
import com.yuanmei.stockeyes.artifacts.TabFragment;
import com.yuanmei.stockeyes.artifacts.back.BackStack;
import com.yuanmei.stockeyes.artifacts.back.StockOverviewBackStackItem;
import com.yuanmei.stockeyes.data.DataProvider;
import com.yuanmei.stockeyes.layouts.StockOverviewLayout;
import com.yuanmei.stockeyes.model.Stock;

import org.json.JSONObject;

import financedata.historicalquotes.Interval;


public class StockListFragment extends Fragment implements TabFragment, OnClickListener, OnLongClickListener, OnDragTileListener {

    private final static String TAG    = "StockListFragment";

    private final static int SWIPE_THRESHOLD_VELOCITY = 150;
    private final static int STOCK_OVERVIEW_HEIGHT    = 165;


    public enum StockOverviewState {
        HIDDEN, OVERVIEW
    }

    //////////////////// ---- Baidu AD ---- START
    private FrameLayout adviewContainer;
    /*
    嵌入SDK需要使用到的ID：
    看股票 的ApiKey： 487zcokagMBwHASlGMevvbIE
    stockeyes_banner 的横幅推广位ID： Y2vRc67lGtBeKaHrQvpf1FGQ

    看股票横幅 ID: 3415592
    看股票 ID: d4144bc3  (Android)
广告位id：3415592
appid：d4144bc3
    */
      public  static final String BAIDU_APP_ID  = "d4144bc3";
      private static final String BAIDU_BANNER_PLACEID = "3415592";
      private AdView              mBaiduAdView;

    private class MyAdListener implements AdViewListener {
        private String stringTag;
        public MyAdListener(String tag) {
            this.stringTag = tag;
        }

        @Override
        public void onAdReady(AdView view) {
            Log.i(stringTag, "    AdReady adview=" + view);
        }

        @Override
        public void onAdShow(JSONObject var){
            Log.i(stringTag, "    AdShow var=" + var);
        }

        @Override
        public void onAdClick(JSONObject var) {
            Log.i(stringTag, "    AdClick var=" + var);
        }

        @Override
        public void onAdFailed(String var){
            Log.i(stringTag, "    AdFailed var=" + var);
        }

        @Override
        public void onAdSwitch(){
            Log.i(stringTag, "    AdSwitch enter");
        }

        @Override
        public void onAdClose(JSONObject var){
            Log.i(stringTag, "    AdClose var=" + var);
        }
    }

    //////////////////// ---- Baidu AD ---- END

    private TableLayout tableLayout;
    private LayoutInflater inflater;
    private View currentlySelectedTile;
    private SparseArray<View> tiles;
    private SearchView searchView;
    private View focusedTileDuringDragAndDrop = null;
    private ActionMode.Callback actionModeCallback;
    private ActionMode actionMode;
    private List<Integer> selectedTiles;
    private AlertDialog removeSelectedStocksDialog;
    private MenuItem searchMenuItem;
    private StockListFragmentCallback callback;

    private ViewFlipper viewFlipper;
    private Animation flipInNextAnimation;
    private Animation flipInPreviousAnimation;
    private Animation flipOutNextAnimation;
    private AnimateStockOverviewContentCallback animateStockOverviewContentCallback;
    private Animation flipOutPreviousAnimation;
    private StockOverviewState stockOverviewState = null;
    private GestureDetector viewFlipperGestureDetector;
    private AlertDialog tileContextualMenuDialog;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setRetainInstance(true);

        this.selectedTiles = new ArrayList<Integer>();
        this.tiles = new SparseArray<View>();

    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        View view = inflater.inflate(R.layout.fragment_stock_list, container,
                false);

        setHasOptionsMenu(true);

        if (isHoneycombOrLater()) {
            this.actionModeCallback = new ActionModeCallback();
        }

        this.adviewContainer = (FrameLayout) view.findViewById(R.id.adviewContainer);
        this.tableLayout = (TableLayout) view.findViewById(R.id.tableLayout);
        this.viewFlipper = (ViewFlipper) view.findViewById(R.id.viewFlipper);

        StockOverviewLayout stockOverviewLayout1 = new StockOverviewLayout(
                getActivity());
        StockOverviewLayout stockOverviewLayout2 = new StockOverviewLayout(
                getActivity());

        this.viewFlipper.addView(stockOverviewLayout1);
        this.viewFlipper.addView(stockOverviewLayout2);

        this.animateStockOverviewContentCallback = new AnimateStockOverviewContentCallback();

        this.flipInNextAnimation = AnimationUtils.loadAnimation(getActivity(),
                R.anim.flip_in_next);
        this.flipInNextAnimation
                .setAnimationListener(new StockOverviewAnimationListener(
                        this.animateStockOverviewContentCallback));

        this.flipInPreviousAnimation = AnimationUtils.loadAnimation(
                getActivity(), R.anim.flip_in_previous);
        this.flipInPreviousAnimation
                .setAnimationListener(new StockOverviewAnimationListener(
                        this.animateStockOverviewContentCallback));

        this.flipOutNextAnimation = AnimationUtils.loadAnimation(getActivity(),
                R.anim.flip_out_next);
        this.flipOutPreviousAnimation = AnimationUtils.loadAnimation(
                getActivity(), R.anim.flip_out_previous);

        this.viewFlipperGestureDetector = new GestureDetector(getActivity(),
                new ViewFlipperGestureDetector());
        this.viewFlipper.setOnTouchListener(new View.OnTouchListener() {
            public boolean onTouch(View v, MotionEvent event) {
                if (StockListFragment.this.viewFlipperGestureDetector
                        .onTouchEvent(event)) {
                    return false;
                }

                return true;
            }
        });

        createDashboardTiles(true);

        // 创建广告View

        AppActivity.setActionBarColorTheme(AppActivity.ActionBarColorTheme.ACTION_BAR_BLACK_THEME);
        AdSettings.setKey(new String[]{"baidu","中国","财经","休闲"});
        Log.i(TAG, "JKP start load BDBannerAD");
        mBaiduAdView = new AdView(this.getActivity(), BAIDU_BANNER_PLACEID);
        mBaiduAdView.setListener(new MyAdListener("StockeyesAdlisten"));
        mBaiduAdView.setVisibility(View.VISIBLE);
//        adviewContainer.addView(mBaiduAdView,
//                new FrameLayout.LayoutParams(
//                        FrameLayout.LayoutParams.MATCH_PARENT,
//                        FrameLayout.LayoutParams.WRAP_CONTENT));
//        adviewContainer.setVisibility(View.VISIBLE);

        return view;
    }

    @Override
    public void onActivityCreated(Bundle savedState) {
        if (this.stockOverviewState == null) {
            setStockOverviewState(StockOverviewState.HIDDEN);
        }

        if (isOverviewVisible()) {
            StockOverviewBackStackItem lastStockOverviewAddedToBackStack = this.callback.getBackStack().getLastStockOverviewAddedToBackStack();
            if (lastStockOverviewAddedToBackStack != null) {
                displayStockOverview(lastStockOverviewAddedToBackStack.getStock(), false);
            }
        }
        super.onActivityCreated(savedState);
    }

    @Override
    public void onAttach(Activity activity) {
        super.onAttach(activity);
        this.callback = (StockListFragmentCallback) activity;
    }

    @Override
    public void onResume() {
        if (isHoneycombOrLater() && this.actionMode != null) {
            this.actionMode = null;
            showContextualActionBar();

            for (Integer position : this.selectedTiles) {
                selectTile(this.tiles.get(position), false);
            }
        }
        super.onResume();


    }

    @Override
    public void onPause() {
        if (this.removeSelectedStocksDialog != null) {
            this.removeSelectedStocksDialog.dismiss();
        }

        if (this.tileContextualMenuDialog != null) {
            this.tileContextualMenuDialog.dismiss();
        }
        super.onPause();
    }

    @Override
    public void onDestroy() {
        Log.i(TAG, "StockList fragment onDestroy");

        if (mBaiduAdView != null) {
            adviewContainer.removeAllViews();
            mBaiduAdView.destroy();
            mBaiduAdView = null;
            Log.i(TAG, "Destroy Baidu banner view");
        }
        super.onDestroy();
    }

    @TargetApi(14)
    @Override
    public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
        inflater.inflate(R.menu.fragment_stock_list, menu);
        this.searchMenuItem = menu.findItem(R.id.menu_item_add);

        if (isIceCreamSandwichOrLater()) {
            SearchManager searchManager = (SearchManager) getActivity().getSystemService(Context.SEARCH_SERVICE);
            this.searchView = (SearchView) this.searchMenuItem.getActionView();
            this.searchView.setSearchableInfo(searchManager.getSearchableInfo(getActivity().getComponentName()));
            this.searchView.setSubmitButtonEnabled(false);
            this.searchView.setIconifiedByDefault(true);
        }

        super.onCreateOptionsMenu(menu, inflater);
    }

    @Override
    public void onPrepareOptionsMenu(Menu menu) {
        //MenuItem shareMenuItem = menu.findItem(R.id.menu_item_share);
        MenuItem prefsMenuItem = menu.findItem(R.id.menu_item_prefs);

        //prefsMenuItem.setVisible(!isOverviewVisible());
        //shareMenuItem.setVisible(isOverviewVisible());
        prefsMenuItem.setVisible(true);
        //shareMenuItem.setVisible(false);

        super.onPrepareOptionsMenu(menu);
    }

    @TargetApi(11)
    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        switch (item.getItemId()) {

            case R.id.menu_item_add:
                requestSearch();
                return true;

            case R.id.menu_item_refresh:
                requestRefreshData();
                return true;

            case R.id.menu_item_analysis:
                Log.d(TAG, "ActionBar menu_item_analysis enter");
                StockTileViewHolder stockTileViewHolder;
                if (this.currentlySelectedTile != null) {
                    stockTileViewHolder = (StockTileViewHolder) this.currentlySelectedTile.getTag();
                } else {
                    stockTileViewHolder = (StockTileViewHolder) this.tiles.get(0).getTag();
                }

                Intent intent = new Intent();
                intent.putExtra(StockAnalysisActivity.ANALYSIS_CODE, stockTileViewHolder.getStock().getCode());
                intent.putExtra(StockAnalysisActivity.ANALYSIS_INTERVAL, Interval.DAILY.getTag());
                intent.setClassName(getActivity(), StockAnalysisActivity.class.getName());
                getActivity().startActivity(intent);
                return true;

            case R.id.menu_item_prefs:
                //requestShowPrefsDialog();

                Intent prefes_intent = new Intent().setClass(this.getActivity(), PrefersActivity.class);
                startActivityForResult(prefes_intent, 0);
                return true;

//			case R.id.menu_item_share: {
//				if (isPriorIceCreamSandwich()) {
//					showShareDialog(null);
//					return true;
//				}
//			}
        }

        return false;
    }

    private Intent getDefaultShareIntent(Integer position) {
        Intent intent = new Intent(android.content.Intent.ACTION_SEND);
        intent.setType("text/plain");

        Stock stock = null;
        if (position == null) {
            if (isOverviewVisible() && this.viewFlipper != null && this.viewFlipper.getTag() != null) {
                stock = this.callback.getStockList().get((Integer) this.viewFlipper.getTag());
            }
        } else {
            stock = this.callback.getStockList().get(position);
        }

        if (stock != null) {
            Resources resources = getActivity().getResources();
            intent.putExtra("symbol", stock.getCode());
            intent.putExtra(android.content.Intent.EXTRA_SUBJECT, String.format(resources.getString(R.string.fragment_stock_overview_share_subject), stock.getCode(), stock.getStringPrice()));

            int resourceIdentifier = resources.getIdentifier("fragment_stock_overview_share_message_" + Constants.STORE, "string", getActivity().getPackageName());

            intent.putExtra(android.content.Intent.EXTRA_TEXT,
                    String.format(resources.getString(resourceIdentifier),
                            stock.getCode(),
                            stock.getStringPrice(),
                            stock.getStringChangeAndChangePercentage(),
                            resources.getString(R.string.application_name)));
        }

        return intent;
    }

    private void display(Stock stock) {
        int position = this.callback.getStockList().indexOf(stock);

        if (this.stockOverviewState == StockOverviewState.HIDDEN) {
            displayStockOverview(position, true);
        } else {
            animateStockOverviewToItem(position);
        }
    }

    private void resetViewFlipperLayoutParms() {
        RelativeLayout.LayoutParams layoutParams = new RelativeLayout.LayoutParams(
                LayoutParams.MATCH_PARENT, Extensions.dpToPixels(
                getResources(), STOCK_OVERVIEW_HEIGHT));

        if (View.GONE == this.adviewContainer.getVisibility()) {
            layoutParams.addRule(RelativeLayout.ALIGN_PARENT_BOTTOM,
                    RelativeLayout.TRUE);
        } else {
            layoutParams.addRule(RelativeLayout.ABOVE, R.id.adviewContainer);
        }

        layoutParams.addRule(RelativeLayout.CENTER_HORIZONTAL,
                RelativeLayout.TRUE);
        this.viewFlipper.setLayoutParams(layoutParams);
    }

    private void displayStockOverview(Integer position, boolean animate) {
//        if (position != null) {
//            setCurrentTile(position);
//            setStockOverviewState(StockOverviewState.OVERVIEW);
//        }
//
//        displayStockInViewFlipper(position);
//
//        resetViewFlipperLayoutParms();
//
//        if (animate) {
//            Animation animation = AnimationUtils.loadAnimation(getActivity()
//                    .getApplicationContext(), R.anim.slide_in_from_bottom);
//            animation.setAnimationListener(new StockOverviewAnimationListener(
//                    this.animateStockOverviewContentCallback));
//            this.viewFlipper.setVisibility(View.VISIBLE);
//            this.viewFlipper.startAnimation(animation);
//        } else {
//            this.viewFlipper.setVisibility(View.VISIBLE);
//        }
//        this.getView().requestLayout();
//        collapseSearchActionView();
//        invalidateOptionsMenu();
    }

    @TargetApi(14)
    private void collapseSearchActionView() {
        if (isIceCreamSandwichOrLater() && this.searchMenuItem != null && this.searchMenuItem.isActionViewExpanded()) {
            this.searchMenuItem.collapseActionView();
        }
    }

    public void hideStockOverview() {
        hideStockOverview(null);
    }

    public void hideStockOverview(final AnimationEndCallback animationEndCallback) {
        if (this.stockOverviewState != null && this.stockOverviewState != StockOverviewState.HIDDEN) {
            setStockOverviewState(StockOverviewState.HIDDEN);

            Animation animation = AnimationUtils.loadAnimation(getActivity().getApplicationContext(), R.anim.slide_out_to_bottom);
            animation.setAnimationListener(new StockOverviewAnimationListener(new AnimationEndCallback() {

                @Override
                public void execute() {
                    StockListFragment.this.viewFlipper.setVisibility(View.GONE);
                    StockListFragment.this.viewFlipper.setInAnimation(null);
                    StockListFragment.this.viewFlipper.setOutAnimation(null);

                    setCurrentTile(null);

                    if (animationEndCallback != null) {
                        animationEndCallback.execute();
                    }
                }
            }));

            this.viewFlipper.startAnimation(animation);

            invalidateOptionsMenu();
        } else if (animationEndCallback != null) {
            animationEndCallback.execute();
        }
    }

    @TargetApi(11)
    private void invalidateOptionsMenu() {
        if (isHoneycombOrLater()) {
            getActivity().invalidateOptionsMenu();
        }
    }

    private void animateStockOverviewToNextItem() {
        this.viewFlipper.setInAnimation(this.flipInPreviousAnimation);
        this.viewFlipper.setOutAnimation(this.flipOutPreviousAnimation);

        int position = (Integer) this.viewFlipper.getTag() + 1;
        if (position >= this.callback.getStockList().size()) {
            position = 0;
        }

        if (!((Integer) this.viewFlipper.getTag()).equals(position)) {
            displayStockInViewFlipper(position);
            setCurrentTile((Integer) this.viewFlipper.getTag());
        }

        invalidateOptionsMenu();
    }

    private void animateStockOverviewToPreviousItem() {
        this.viewFlipper.setInAnimation(this.flipInNextAnimation);
        this.viewFlipper.setOutAnimation(this.flipOutNextAnimation);

        int position = (Integer) this.viewFlipper.getTag() - 1;
        if (position < 0) {
            position = this.callback.getStockList().size() - 1;
        }

        if (!((Integer) this.viewFlipper.getTag()).equals(position)) {
            displayStockInViewFlipper(position);
            setCurrentTile((Integer) this.viewFlipper.getTag());
        }

        invalidateOptionsMenu();
    }

    private void displayStockInViewFlipper(Integer position) {
        int availableFlipperChild = this.viewFlipper.getDisplayedChild() == 0
                ? 1
                : 0;

        StockOverviewLayout stockOverviewLayout = (StockOverviewLayout) this.viewFlipper.getChildAt(availableFlipperChild);

        if (position != null) {
            stockOverviewLayout.setStock(this.callback.getStockList().get(position));
        } else {
            stockOverviewLayout.setStock(null);
        }

        this.viewFlipper.setTag(position);
        this.viewFlipper.setDisplayedChild(availableFlipperChild);
    }

    private void animateStockOverviewToItem(Integer position) {
        Integer currentStock = (Integer) this.viewFlipper.getTag();

        int animateFrom = currentStock == null
                ? Integer.MIN_VALUE
                : currentStock;

        int animateTo = position == null
                ? Integer.MAX_VALUE
                : position;

        if (animateTo < animateFrom) {
            this.viewFlipper.setInAnimation(this.flipInNextAnimation);
            this.viewFlipper.setOutAnimation(this.flipOutNextAnimation);
        } else {
            this.viewFlipper.setInAnimation(this.flipInPreviousAnimation);
            this.viewFlipper.setOutAnimation(this.flipOutPreviousAnimation);
        }

        setCurrentTile(position);
        displayStockInViewFlipper(position);

        invalidateOptionsMenu();
    }

    private void setCurrentTile(Integer position) {
        if (position != null && !position.equals(Integer.MAX_VALUE)) {
            this.callback.getBackStack().add(new StockOverviewBackStackItem(position));
        } else {
            this.callback.getBackStack().removeAllStockOverviewItems();
        }

        setSelection(position);
    }

    public boolean back() {
        boolean handled = false;

        if (this.stockOverviewState != StockOverviewState.HIDDEN) {
            if (this.callback.getBackStack().getStockOverviewItemCount() == 0) {
                hideStockOverview();
                handled = true;
            } else {
                animateStockOverviewToItem(this.callback.getBackStack().getLastStockOverviewAddedToBackStack().getStock());
                handled = true;
            }
        }

        return handled;
    }

    private boolean isOverviewVisible() {
        return this.stockOverviewState != null && this.stockOverviewState != StockOverviewState.HIDDEN;
    }

    @TargetApi(11)
    private void showContextualActionBar() {
        hideStockOverview();

        if (this.actionMode == null) {
            this.actionMode = ((FragmentActivity) getActivity()).startActionMode(this.actionModeCallback);
            updateContextualActionBar();
        }
    }

    @TargetApi(11)
    @Override
    public void hideContextualActionBar() {
        if (isHoneycombOrLater()) {
            if (this.actionMode != null) {
                this.actionMode.finish();
            }
        }
    }

    private long mLastClickTime = 0;
    private final static long DOUBLE_CLICK_INTERVAL = 1000;

    @Override
    public void onClick(View view) {
        long delta_time = System.currentTimeMillis() - mLastClickTime;
        mLastClickTime = System.currentTimeMillis();

        StockTileViewHolder stockTileViewHolder = (StockTileViewHolder) view.getTag();
        if (stockTileViewHolder != null) {
            if (actionMode != null) {
                selectTile(view, true);
            } else {
//                if (!view.equals(this.currentlySelectedTile)) {
//                    display(stockTileViewHolder.getStock());
//                }
                //            if (delta_time < DOUBLE_CLICK_INTERVAL) //Click start sa_activity
                {
                    Log.d(TAG, "Double Click enter delta_time=" + delta_time);
                    Intent intent = new Intent();
                    intent.putExtra(StockAnalysisActivity.ANALYSIS_CODE, stockTileViewHolder.getStock().getCode());
                    intent.putExtra(StockAnalysisActivity.ANALYSIS_INTERVAL, Interval.DAILY.getTag());
                    intent.setClassName(getActivity(), StockAnalysisActivity.class.getName());
                    getActivity().startActivity(intent);
                }
            }
        } else {
            requestSearch();
        }
    }

    @Override
    public boolean onLongClick(View view) {
        if (isHoneycombOrLater()) {
            if (this.actionMode == null) {
                showContextualActionBar();
                selectTile(view, false);
                return true;
            }

            startDraggingTile(view);
            return true;
        } else {
            selectTile(view, false);
            showTileContextualMenu(view);
            return true;
        }
    }

    private void showTileContextualMenu(final View view) {
        if (this.tileContextualMenuDialog == null || !this.tileContextualMenuDialog.isShowing()) {
            final StockTileViewHolder stockTileViewHolder = (StockTileViewHolder) view.getTag();
            AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());

            builder.setTitle(String.format(getString(R.string.fragment_stock_list_tile_contextual_menu_title), stockTileViewHolder.getStock().getCode()));

            builder.setItems(new CharSequence[]{
                    getString(R.string.fragment_stock_list_tile_contextual_menu_share_item),
                    getString(R.string.fragment_stock_list_tile_contextual_menu_delete_item),
                    getString(R.string.label_cancel)}, new DialogInterface.OnClickListener() {

                public void onClick(DialogInterface dialog, int item) {
                    switch (item) {
                        case 0:
                            showShareDialog(view);
                            break;
                        case 1:
                            dialog.dismiss();
                            showDeleteWarningDialog(stockTileViewHolder.getPosition());
                            break;
                        case 2:
                            dialog.dismiss();
                            break;
                    }
                }
            });

            this.tileContextualMenuDialog = builder.create();
            this.tileContextualMenuDialog.setOnDismissListener(new OnDismissListener() {

                @Override
                public void onDismiss(DialogInterface dialog) {
                    StockListFragment.this.selectedTiles.clear();
                    StockTileProcessor.updateTileColorBasedOnStock(StockListFragment.this, view);
                }
            });

            this.tileContextualMenuDialog.show();
        }
    }

    private void selectTile(View tile, boolean toggle) {
        StockTileViewHolder stockTileViewHolder = (StockTileViewHolder) tile.getTag();

        if (!stockTileViewHolder.isFixed()) {
            if (toggle && this.selectedTiles.contains(stockTileViewHolder.getPosition())) {
                this.selectedTiles.remove((Integer) stockTileViewHolder.getPosition());

                if (this.selectedTiles.size() == 0 && !isHoneycombOrLater()) {
                    hideContextualActionBar();
                }
            } else if (!this.selectedTiles.contains(stockTileViewHolder.getPosition())) {
                this.selectedTiles.add(stockTileViewHolder.getPosition());
            }

            StockTileProcessor.updateTileColor(this, tile, this.selectedTiles);
            updateContextualActionBar();
        }
    }

    @TargetApi(11)
    private void updateContextualActionBar() {
        if (isHoneycombOrLater()) {
            if (this.actionMode != null) {
                this.actionMode.setTitle(String.format(getResources().getString(R.string.label_cab_selected), this.selectedTiles.size()));
                this.actionMode.invalidate();
            }
        }
    }

    @TargetApi(11)
    @Override
    public boolean onDrag(View tile2, DragEvent event) {
        View tile1 = (View) event.getLocalState();

        StockTileViewHolder stockTileViewHolder1 = (StockTileViewHolder) tile1.getTag();
        StockTileViewHolder stockTileViewHolder2 = (StockTileViewHolder) tile2.getTag();

        switch (event.getAction()) {
            case DragEvent.ACTION_DRAG_STARTED:
                tile1.setVisibility(View.INVISIBLE);

                if (stockTileViewHolder1.getPosition() != stockTileViewHolder2.getPosition()) {
                    return true;
                }

                return false;

            case DragEvent.ACTION_DRAG_ENTERED:
                this.focusedTileDuringDragAndDrop = tile2;
                StockTileProcessor.updateTileColorToDropReceptor(tile2);
                tile2.invalidate();

                return true;

            case DragEvent.ACTION_DRAG_LOCATION:
                return true;

            case DragEvent.ACTION_DRAG_EXITED:
                this.focusedTileDuringDragAndDrop = null;
                StockTileProcessor.updateTileColor(this, tile2, this.selectedTiles);
                tile2.invalidate();

                return true;

            case DragEvent.ACTION_DROP:
                this.focusedTileDuringDragAndDrop = null;
                swapTiles(tile1, tile2);
                return true;

            case DragEvent.ACTION_DRAG_ENDED:
                if (this.focusedTileDuringDragAndDrop != null) {
                    swapTiles(tile1, this.focusedTileDuringDragAndDrop);
                    this.focusedTileDuringDragAndDrop = null;

                    return true;
                }

                StockTileProcessor.updateTileColor(this, tile1, this.selectedTiles);
                StockTileProcessor.updateTileColor(this, tile2, this.selectedTiles);

                tile1.setVisibility(View.VISIBLE);
                tile2.setVisibility(View.VISIBLE);

                tile1.invalidate();
                tile2.invalidate();

                return true;

            default:
                return true;
        }
    }

    @TargetApi(11)
    private void startDraggingTile(View tile) {
        StockTileViewHolder stockTileViewHolder = (StockTileViewHolder) tile.getTag();
        this.selectedTiles.remove((Integer) stockTileViewHolder.getPosition());
        updateContextualActionBar();

        ClipData.Item item = new ClipData.Item(stockTileViewHolder.toString());
        ClipData clipData = new ClipData(stockTileViewHolder.toString(), new String[0], item);

        View.DragShadowBuilder dragShadowBuilder = new DragShadowBuilder(tile);
        tile.startDrag(clipData, dragShadowBuilder, tile, 0);
    }

    private void swapTiles(View tile1, View tile2) {
        StockTileViewHolder stockTileViewHolder1 = (StockTileViewHolder) tile1.getTag();
        StockTileViewHolder stockTileViewHolder2 = (StockTileViewHolder) tile2.getTag();

        this.callback.reorderStocks(stockTileViewHolder1.getStock(), stockTileViewHolder2.getStock());

        this.selectedTiles.remove((Integer) stockTileViewHolder1.getPosition());
        this.selectedTiles.remove((Integer) stockTileViewHolder2.getPosition());
        updateContextualActionBar();

        Stock tempStock = stockTileViewHolder1.getStock();
        stockTileViewHolder1.setStock(stockTileViewHolder2.getStock());
        stockTileViewHolder2.setStock(tempStock);

        tile1.setTag(stockTileViewHolder1);
        tile2.setTag(stockTileViewHolder2);

        this.tiles.remove(stockTileViewHolder1.getPosition());
        this.tiles.remove(stockTileViewHolder2.getPosition());

        this.tiles.put(stockTileViewHolder1.getPosition(), tile1);
        this.tiles.put(stockTileViewHolder2.getPosition(), tile2);

        stockTileViewHolder1.refresh(getResources());
        stockTileViewHolder2.refresh(getResources());

        tile1.setVisibility(View.VISIBLE);
        tile2.setVisibility(View.VISIBLE);

        tile1.invalidate();
        tile2.invalidate();
    }

    public void setSelection(Integer position) {
        if (position != null) {
            View tile = this.tiles.get(position);

            if (this.currentlySelectedTile != null) {
                StockTileProcessor.updateTileColor(this, this.currentlySelectedTile, this.selectedTiles);
            }

            this.currentlySelectedTile = tile;

            StockTileViewHolder stockTileViewHolder = (StockTileViewHolder) tile.getTag();

            Extensions.applyPattern(
                    getResources(),
                    stockTileViewHolder.getTileLayout(),
                    PatternBackgroundColor.BLUE);
        } else {
            if (this.currentlySelectedTile != null) {
                StockTileProcessor.updateTileColor(this, this.currentlySelectedTile, this.selectedTiles);
            }

            this.currentlySelectedTile = null;
        }
    }

    public void refresh(boolean hardReset) {
        hideStockOverview();
        collapseSearchActionView();
        createDashboardTiles(hardReset);
    }

    private void createDashboardTiles(boolean restart) {
        StockTileProcessor.create(
                this,
                this.tableLayout,
                this.callback.getStockList(),
                this.tiles,
                restart);
    }

    public void refreshStockInformation(List<Stock> stocks) {

        try {
            for (Stock stock : stocks) {
                View view = findTile(stock);
                StockTileViewHolder stockTileViewHolder = (StockTileViewHolder) view.getTag();
                if (stockTileViewHolder != null) {
                    stockTileViewHolder.refresh(getActivity().getResources(), stock);
                }

                if (this.viewFlipper != null && this.viewFlipper.getTag() != null) {
                    StockOverviewLayout stockOverviewLayout = (StockOverviewLayout) this.viewFlipper.getChildAt(this.viewFlipper.getDisplayedChild());
                    if (stockOverviewLayout != null && stockOverviewLayout.getStock().getCode().equals(stock.getCode())) {
                        stockOverviewLayout.setStock(stock);
                    }
                }
            }
            SharedPreferences sharedPreferences = getActivity().getSharedPreferences(Constants.PREFERENCES, Context.MODE_PRIVATE);
            boolean refresh = sharedPreferences.getBoolean(Constants.PREFERENCE_COLLECTOR_REFRESH, false);
            if (refresh) {
                Editor editor = sharedPreferences.edit();
                editor.putBoolean(Constants.PREFERENCE_COLLECTOR_REFRESH, false);
                editor.commit();
                Toast.makeText(getActivity().getApplicationContext(), getString(R.string.toast_refresh_message),
                        Toast.LENGTH_LONG).show();
            }
        } catch (IllegalStateException e) {
			/*
			 * For some reason, some devices are reporting an IllegalStateException when trying to
			 * access the method
			 * getResources() from above. The full error message is the following:
			 * java.lang.IllegalStateException: Fragment StockListFragment{40540d98} not attached to
			 * Activity
			 * 
			 * Since this error happens while refreshing the stock information, I'm going to ignore
			 * it.
			 */

            Log.e(TAG, e.getMessage(), e);
        }
    }

    private View findTile(Stock stock) {
        for (int i = 0; i < this.tiles.size(); i++) {
            View view = this.tiles.valueAt(i);

            StockTileViewHolder stockTileViewHolder = (StockTileViewHolder) view.getTag();
            if (stockTileViewHolder.getStock().getCode().equals(stock.getCode())) {
                return view;
            }
        }

        return null;
    }

    @TargetApi(14)
    private void requestSearch() {
        hideContextualActionBar();

        if (isIceCreamSandwichOrLater()) {
            hideStockOverview(new AnimationEndCallback() {

                @Override
                public void execute() {
                    StockListFragment.this.searchMenuItem.expandActionView();
                }
            });
        } else {
            getActivity().onSearchRequested();
        }
    }


    private void requestRefreshData() {
        SharedPreferences sharedPreferences = getActivity().getSharedPreferences(Constants.PREFERENCES, Context.MODE_PRIVATE);
        Editor editor = sharedPreferences.edit();
        editor.putBoolean(Constants.PREFERENCE_COLLECTOR_REFRESH, true);
        editor.commit();
        Log.d(TAG, "Performing manual sync global market information collection...");

        DataProvider.startStockQuoteCollectorService(getActivity().getApplicationContext(), null);
    }

    private void showDeleteWarningDialog(Integer position) {
        if (this.removeSelectedStocksDialog == null || !this.removeSelectedStocksDialog.isShowing()) {

            if (position == null) {
                if (this.selectedTiles.size() == 1) {
                    position = ((StockTileViewHolder) this.tiles.get(this.selectedTiles.get(0)).getTag()).getPosition();
                }
            }

            final Stock stock = position != null
                    ? ((StockTileViewHolder) this.tiles.get(position).getTag()).getStock()
                    : null;

            AlertDialog.Builder removeSelectedStocksDialogBuilder = new AlertDialog.Builder(getActivity());

            String message = this.callback.getRemoveWarningDialogMessage(stock);

            View view = getLayoutInflater().inflate(R.layout.dialog_message, null);
            TextView textView = (TextView) view.findViewById(R.id.textView);
            textView.setText(message);

            removeSelectedStocksDialogBuilder
                    .setIcon(R.drawable.ic_warning)
                    .setTitle(this.callback.getRemoveWarningDialogTitle(stock))
                    .setView(view)
                    .setPositiveButton(R.string.label_remove, new DialogInterface.OnClickListener() {

                        @Override
                        public void onClick(DialogInterface dialog, int which) {
                            removeSelectedStocks(stock);
                        }
                    })
                    .setNegativeButton(R.string.label_cancel, null);

            this.removeSelectedStocksDialog = removeSelectedStocksDialogBuilder.create();
            this.removeSelectedStocksDialog.show();
        }
    }

    private void showShareDialog(View view) {
        Integer position = null;
        if (view != null) {
            StockTileViewHolder stockTileViewHolder = (StockTileViewHolder) view.getTag();
            position = stockTileViewHolder.getPosition();
        }

        startActivity(Intent.createChooser(getDefaultShareIntent(position), getResources().getString(R.string.fragment_stock_overview_share_dialog_title)));
    }

    private void removeSelectedStocks(Stock stock) {
        List<Stock> stockListToRemove = new ArrayList<Stock>();

        if (stock == null) {
            for (int position : this.selectedTiles) {
                stockListToRemove.add(((StockTileViewHolder) this.tiles.get(position).getTag()).getStock());
            }
        } else {
            stockListToRemove.add(stock);
        }

        this.callback.removeStocks(stockListToRemove);

        hideContextualActionBar();
        createDashboardTiles(false);
    }

    public StockOverviewState getStockOverviewState() {
        return this.stockOverviewState;
    }

    public void setStockOverviewState(StockOverviewState stockOverviewState) {
        this.stockOverviewState = stockOverviewState;
    }

    private LayoutInflater getLayoutInflater() {
        if (this.inflater == null) {
            this.inflater = (LayoutInflater) getActivity().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
        }

        return this.inflater;
    }

    @TargetApi(11)
    private class ActionModeCallback implements ActionMode.Callback {

        @Override
        public boolean onCreateActionMode(ActionMode mode, Menu menu) {
            MenuInflater inflater = mode.getMenuInflater();
            inflater.inflate(R.menu.fragment_stock_list_cab, menu);

            return true;
        }

        @Override
        public boolean onPrepareActionMode(ActionMode mode, Menu menu) {
            MenuItem deleteMenuItem = menu.findItem(R.id.menu_item_delete);
            deleteMenuItem.setVisible(StockListFragment.this.selectedTiles.size() > 0);

            return false;
        }

        @Override
        public boolean onActionItemClicked(ActionMode mode, MenuItem item) {
            if (item.getItemId() == R.id.menu_item_delete) {
                showDeleteWarningDialog(null);
            }

            return false;
        }

        @Override
        public void onDestroyActionMode(ActionMode mode) {
            StockListFragment.this.actionMode = null;

            for (Integer position : StockListFragment.this.selectedTiles) {
                StockTileProcessor.updateTileColorBasedOnStock(StockListFragment.this, StockListFragment.this.tiles.get(position));
            }

            StockListFragment.this.selectedTiles.clear();
        }
    }

    public interface StockListFragmentCallback {
        public List<Stock> getStockList();

        public void removeStocks(List<Stock> stocks);

        public void reorderStocks(Stock stock1, Stock stock2);

        public String getRemoveWarningDialogTitle(Stock stock);

        public String getRemoveWarningDialogMessage(Stock stock);

        public void onStockOverviewAddedToBackStack();

        public void onStockOverviewClearBackStack();

        public BackStack getBackStack();
    }

    private interface AnimationEndCallback {
        public void execute();
    }

    private class StockOverviewAnimationListener implements AnimationListener {

        private final AnimationEndCallback callback;

        public StockOverviewAnimationListener(AnimationEndCallback callback) {
            this.callback = callback;
        }

        @Override
        public void onAnimationStart(Animation animation) {
        }

        @Override
        public void onAnimationEnd(Animation animation) {
            if (this.callback != null) {
                this.callback.execute();
            }
        }

        @Override
        public void onAnimationRepeat(Animation animation) {
        }

    }

    private class AnimateStockOverviewContentCallback implements AnimationEndCallback {

        @Override
        public void execute() {
            StockOverviewLayout stockOverviewLayout = (StockOverviewLayout) StockListFragment.this.viewFlipper.getChildAt(StockListFragment.this.viewFlipper.getDisplayedChild());
            stockOverviewLayout.animateContent();
        }
    }

    private class ViewFlipperGestureDetector extends SimpleOnGestureListener {

        @Override
        public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {
            StockOverviewLayout stockOverviewLayout = (StockOverviewLayout) StockListFragment.this.viewFlipper.getChildAt(StockListFragment.this.viewFlipper.getDisplayedChild());

            int swipeMinDistance = stockOverviewLayout.getHeight() / 3;

            try {
                if (e1.getX() - e2.getX() > swipeMinDistance && Math.abs(velocityX) > SWIPE_THRESHOLD_VELOCITY) {
                    animateStockOverviewToNextItem();
                    return true;
                }

                if (e2.getX() - e1.getX() > swipeMinDistance && Math.abs(velocityX) > SWIPE_THRESHOLD_VELOCITY) {
                    animateStockOverviewToPreviousItem();
                    return true;
                }

                if (e2.getY() - e1.getY() > swipeMinDistance && Math.abs(velocityY) > SWIPE_THRESHOLD_VELOCITY) {
                    StockListFragment.this.hideStockOverview();
                    return true;
                }

                if (e1.getY() - e2.getY() > swipeMinDistance && Math.abs(velocityY) > SWIPE_THRESHOLD_VELOCITY) {
                }
            } catch (Exception e) {
            }

            return false;
        }
    }

}
